package org.xx.armory.spring5.mq;

import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.Objects;

import static java.lang.Long.parseLong;
import static org.xx.armory.commons.SysUtils.copyDate;
import static org.xx.armory.commons.Validators.rejectIfNonPositive;
import static org.xx.armory.commons.Validators.rejectIfNull;

/**
 * 消息ID。
 */
public final class MessageQueueId {
    public static final MessageQueueId EMPTY = new MessageQueueId();

    private final long id;
    private final Date timestamp;

    private MessageQueueId() {
        this.id = 0L;
        this.timestamp = null;
    }

    public MessageQueueId(
            long id
    ) {
        this.id = rejectIfNonPositive(id, "id");
        this.timestamp = new Date();
    }

    public MessageQueueId(
            long id,
            Date timestamp
    ) {
        this.id = rejectIfNonPositive(id, "id");
        this.timestamp = copyDate(rejectIfNull(timestamp, "timestamp"));
    }

    /**
     * 将字符串解析为消息队列ID。
     *
     * @param s
     *         待解析的字符串。
     * @return 解析结果。如果参数 {@code s} 是 {@code null} 或者只包含空字符串，那么返回 {@link #EMPTY} 。
     * @throws IllegalArgumentException
     *         如果待解析的字符串格式不正确。
     * @throws NumberFormatException
     *         如果待解析的字符串格式不正确。
     */
    public static MessageQueueId parse(
            String s
    ) {
        if (s.isBlank()) {
            return EMPTY;
        }

        final var ps = StringUtils.split(s.strip(), ',');
        if (ps.length != 2) {
            throw new IllegalArgumentException("Illegal string: " + s);
        }
        return new MessageQueueId(parseLong(ps[0]), new Date(parseLong(ps[1])));
    }

    public long getId() {
        return this.id;
    }

    public Date getTimestamp() {
        return this.timestamp;
    }

    public boolean isEmpty() {
        return this.id == 0 || this.timestamp == null;
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.id, this.timestamp);
    }

    @Override
    public boolean equals(
            Object obj
    ) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof MessageQueueId)) {
            return false;
        }
        final var other = (MessageQueueId) obj;
        return this.id == other.id && Objects.equals(this.timestamp, other.timestamp);
    }

    @Override
    public String toString() {
        return this.isEmpty() ? "" : this.id + "," + this.timestamp.getTime();
    }
}
